/***********************************************************************************************************************
*  OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
*  See also https://openstudio.net/license
***********************************************************************************************************************/

#ifndef GLTF_GLTFFORWARDTRANSLATOR_HPP
#define GLTF_GLTFFORWARDTRANSLATOR_HPP

#include "GltfAPI.hpp"

#include "GltfMetaData.hpp"
#include "GltfUserData.hpp"

#include "../utilities/core/Path.hpp"
#include "../utilities/core/Logger.hpp"
#include "../utilities/core/StringStreamLogSink.hpp"

namespace tinygltf {
class Model;
}

namespace openstudio {
namespace model {
  class Model;
}

namespace gltf {

  // TODO: update this docstring, it's always been out of sync

  /** GltfForwardTranslator converts an OpenStudio Model to GLTF format. There are two variations of the GLTF format,
    *   a triangulated one which is suitable for rendering with GLTF and non-triangulated one that preserves all vertices in a
    *   surface for conversion to OpenStudio Model format.
    *
    *   The FloorplanJS in the Utilities/Geometry project converts a FloorspaceJS JSON file to GLTF format, code should be shared between these two classes as much as possible.
    */
  class GLTF_API GltfForwardTranslator
  {
   public:
    GltfForwardTranslator();

    /** Convert an OpenStudio Model to Gltf format */
    bool modelToGLTF(const model::Model& model, const path& outputPath);
    bool modelToGLTF(const model::Model& model, std::function<void(double)> updatePercentage, const path& outputpath);

    /** Convert an OpenStudio Model to Gltf format but as a JSON string */
    std::string modelToGLTFString(const model::Model& model);

    /** @name QA / QC convenience methods */
    //@{
    /** load minimal gltf for QA/QC */
    bool loadGLTF(const path& inputPath, const path& inputNonEmbededpath);
    /** load minimal gltf for QA/QC */
    bool loadGLTF(const path& inputPath);

    GltfMetaData getMetaData() const;
    std::vector<GltfUserData> getUserDataCollection() const;
    boost::optional<GltfUserData> getUserDataBySurfaceName(const std::string& surfaceName) const;

    /** Get warning messages generated by the last translation. */
    std::vector<LogMessage> warnings() const;

    /** Get error messages generated by the last translation. */
    std::vector<LogMessage> errors() const;
    //@}

   private:
    boost::optional<tinygltf::Model> toGltfModel(const model::Model& model, std::function<void(double)> updatePercentage);

    REGISTER_LOGGER("openstudio.gltf.GltfForwardTranslator");

    StringStreamLogSink m_logSink;

    GltfMetaData m_gltfMetaData;
    std::vector<GltfUserData> m_userDataCollection;

    // TODO: make this a member?
    // std::vector<GltfMaterialData> allMaterials;
  };

}  // namespace gltf
}  // namespace openstudio

#endif  // GLTF_GLTFFORWARDTRANSLATOR_HPP
